home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / c-lang / vbcc.lha / vbcc / rd.c < prev    next >
C/C++ Source or Header  |  1996-05-15  |  18KB  |  457 lines

  1. /*  $VER: vbcc (rd.c) V0.3     */
  2. /*  verfuegbare Definitionen und constant propagation   */
  3.  
  4. #include "opt.h"
  5.  
  6.  
  7. /*  fuer verfuegbare Definitionen   */
  8. unsigned int dcount;
  9. size_t dsize;
  10. struct IC **dlist;
  11. unsigned char **defs;       /*  gibt an, welche Definitionen, welche    */
  12.                             /*  Variablen definieren                    */
  13. /*  alle Definitionen, globaler oder Adr. fuer propagation etc.         */
  14. unsigned char *rd_globals,*rd_address,*rd_statics,*rd_drefs;
  15. /*  dasseble, aber hier nur die undefs  */
  16. unsigned char *rd_defs,*rd_tmp,*rd_parms;
  17.  
  18. int compare_const(union atyps *q1,union atyps *q2,int t)
  19. /*  vergleiht zwei Konstanten; -1, wenn q1<q2; 0, wenn q1==q1; 1 sonst  */
  20. {
  21.     zdouble d1,d2;zlong l1,l2;zulong u1,u2;zpointer p1,p2;
  22.     t&=31;
  23.     eval_const(q1,t);p1=vpointer;d1=vdouble;l1=vlong;u1=vulong;
  24.     eval_const(q2,t);p2=vpointer;d2=vdouble;l2=vlong;u2=vulong;
  25.     if(t==POINTER) return(zpleq(p2,p1)?!zpeqto(p1,p2):-1);
  26.     if(t==DOUBLE||t==FLOAT) return(zdleq(d2,d1)?!zdeqto(d1,d2):-1);
  27.     if(t&UNSIGNED) return(zulleq(u2,u1)?!zuleqto(u1,u2):-1);
  28.     return(zlleq(l2,l1)?!zleqto(l1,l2):-1);
  29.     ierror(0);
  30. }
  31.  
  32. void print_rd(unsigned char *bitvector)
  33. /*  druckt Definitionen in einem Bitvektor */
  34. {
  35.     unsigned int i;
  36.     if(!bitvector) {printf("reaching definitions not available\n");return;}
  37.     for(i=1;i<=dcount;i++)
  38.         if(BTST(bitvector,i)) {printf("%3d:",i);pric2(stdout,dlist[i]);}
  39.     for(i=0;i<vcount-rcount;i++)
  40.         if(BTST(bitvector,i+dcount+1)) printf("%3d:\t\tundefined\t->%s\n",i+dcount+1,vilist[i]->identifier);
  41.     for(i=vcount-rcount;i<vcount;i++)
  42.         if(BTST(bitvector,i+dcount+1)) printf("%3d:\t\tundefined\t->(%s)\n",i+dcount+1,vilist[i]->identifier);
  43. }
  44.  
  45. void num_defs(void)
  46. /*  Numeriert alle Variablendefinitionen (nur elementare Typen noetig)  */
  47. /*  und erzeugt diverse Bitvektoren.                                    */
  48. {
  49.     int i=0;struct IC *p;
  50.     if(DEBUG&1024) printf("numerating definitions\n");
  51.     for(p=first_ic;p;p=p->next){
  52.         if(!(p->z.flags&VAR)){p->defindex=0;continue;}
  53. /*        if((p->z.v->vtyp->flags&15)>POINTER){p->defindex=0;continue;}*/
  54.         p->defindex=++i;
  55.     }
  56.     dcount=i;dsize=(dcount+CHAR_BIT+vcount)/CHAR_BIT;    /* +1, da bei 1 anfaengt */
  57.     if(DEBUG&1024) printf("%lu definitions, dsize=%lu\n",(unsigned long)dcount,(unsigned long)dsize);
  58.     /*  fuer jede Variable wird eine kuenstliche unbestimmte Def. erzeugt   */
  59.     /*  Feld erzeugen, dass zu jeder Variable alle Definitionen erhaelt    */
  60.     defs=mymalloc(sizeof(unsigned char *)*vcount);
  61.     for(i=0;i<vcount;i++){
  62.         defs[i]=mymalloc(dsize);
  63.         memset(defs[i],0,dsize);
  64.         BSET(defs[i],i+dcount+1);
  65.     }
  66.     dlist=mymalloc((dcount+1)*sizeof(struct IC *));
  67.     rd_globals=mymalloc(dsize);
  68.     memset(rd_globals,0,dsize);
  69.     rd_statics=mymalloc(dsize);
  70.     memset(rd_statics,0,dsize);
  71.     rd_address=mymalloc(dsize);
  72.     memset(rd_address,0,dsize);
  73.     rd_drefs=mymalloc(dsize);
  74.     memset(rd_drefs,0,dsize);
  75.  
  76.     for(p=first_ic;p;p=p->next){
  77.         if(p->defindex){
  78.             i=p->z.v->index;
  79.             if(p->z.flags&DREFOBJ) i+=vcount-rcount;
  80.             BSET(defs[i],p->defindex);
  81.             dlist[p->defindex]=p;
  82.         }
  83.     }
  84.     if(DEBUG&2048){
  85.         for(i=1;i<=dcount;i++){ printf("Def%3d: ",i);pric2(stdout,dlist[i]);}
  86.         for(i=0;i<vcount;i++){
  87.             printf("Definitionen fuer <%s>:\n",vilist[i]->identifier);
  88.             print_rd(defs[i]);
  89.         }
  90.     }
  91.     for(i=0;i<vcount-rcount;i++){   /*  rd_globals berechnen    */
  92.         if(vilist[i]->vtyp->flags&CONST) continue;
  93.         if(vilist[i]->nesting==0||vilist[i]->storage_class==EXTERN) bvunite(rd_globals,defs[i],dsize);
  94.         if(vilist[i]->flags&USEDASADR) bvunite(rd_address,defs[i],dsize);
  95.         if(vilist[i]->storage_class==STATIC) bvunite(rd_statics,defs[i],dsize);
  96.         if(i<rcount){
  97.             bvunite(rd_address,defs[i+vcount-rcount],dsize);
  98.             bvunite(rd_globals,defs[i+vcount-rcount],dsize);
  99.             bvunite(rd_drefs,defs[i+vcount-rcount],dsize);
  100.         }
  101.     }
  102.     rd_parms=mymalloc(dsize);
  103.     memset(rd_parms,0,dsize);
  104.     for(i=0;i<vcount-rcount;i++){
  105.         if(vilist[i]->offset<0){
  106.             BSET(rd_parms,i+dcount+1);
  107.             if(i<rcount) BSET(rd_parms,i+vcount-rcount+dcount+1);
  108.         }
  109.     }
  110. /*    if(DEBUG&1024){printf("rd_globals:\n");print_rd(rd_globals);}*/
  111. }
  112. void reaching_definitions(struct flowgraph *fg)
  113. /*  berechnet die verfuegbaren Definitionen fuer jeden Block    */
  114. {
  115.     struct flowgraph *g;struct IC *p;unsigned char *tmp;int changed,pass;
  116.     /*  rd_gen und rd_kill fuer jeden Block berechnen   */
  117.     if(DEBUG&1024) printf("analysing reaching definitions\n");
  118.     tmp=mymalloc(dsize);
  119.     g=fg;
  120.     while(g){
  121.         g->rd_in=mymalloc(dsize);
  122.         memset(g->rd_in,0,dsize);
  123.         g->rd_out=mymalloc(dsize);
  124.         memset(g->rd_out,0,dsize);
  125.         g->rd_gen=mymalloc(dsize);
  126.         memset(g->rd_gen,0,dsize);
  127.         g->rd_kill=mymalloc(dsize);
  128.         memset(g->rd_kill,0,dsize);
  129.         p=g->end;
  130.         while(p){
  131.             if(p->defindex){
  132.                 if(!BTST(g->rd_kill,p->defindex)){
  133.                     int i;
  134.                     BSET(g->rd_gen,p->defindex);
  135.                     i=p->z.v->index;
  136.                     if(p->z.flags&DREFOBJ) i+=vcount-rcount;
  137.                     memcpy(tmp,defs[i],dsize);
  138.                     bvdiff(tmp,g->rd_gen,dsize);
  139.                     bvunite(g->rd_kill,tmp,dsize);
  140.                     BCLR(g->rd_kill,p->defindex);
  141.                     /*  bei Zuweisung an x undefined->(x) setzen    */
  142.                     if(i<rcount&&!BTST(g->rd_kill,dcount+1+i+vcount-rcount))
  143.                         BSET(g->rd_gen,dcount+1+i+vcount-rcount);
  144.                 }
  145.             }
  146.             if((p->z.flags&(VAR|DREFOBJ))==VAR){
  147.                 if(p->z.v->nesting==0||(p->z.v->flags&USEDASADR)){
  148.                     memcpy(tmp,rd_drefs,dsize);
  149.                     bvdiff(tmp,g->rd_kill,dsize);
  150.                     bvunite(g->rd_gen,tmp,dsize);
  151.                 }
  152.             }
  153.             if(p->code==CALL||(p->z.flags&DREFOBJ)){
  154.             /*  Zuweisung ueber Zeiger oder Funktionsaufruf zerstoert viel  */
  155.                 /*  alle globalen, statischen etc. evtl. nach gen       */
  156.                 memcpy(tmp,rd_globals,dsize);
  157.                 bvunite(tmp,rd_address,dsize);
  158.                 if(p->code==CALL/*&&!norek*/) bvunite(tmp,rd_statics,dsize);
  159.                 bvdiff(tmp,g->rd_kill,dsize);
  160.                 bvunite(g->rd_gen,tmp,dsize);
  161.             }
  162.             if(p==g->start) break;
  163.             p=p->prev;
  164.         }
  165.         memcpy(g->rd_out,g->rd_gen,dsize);
  166.         g=g->normalout;
  167.     }
  168.  
  169.     /*  rd_in und rd_out fuer jeden Block berechnen */
  170.     /*  out(b)=gen(B) vorinitialisiert              */
  171.     if(DEBUG&1024) {printf("pass:");pass=0;}
  172.     do{
  173.         if(DEBUG&1024) {printf(" %d",++pass);fflush(stdout);}
  174.         changed=0;
  175.         g=fg;
  176.         while(g){
  177.             struct flowlist *lp;
  178.             /*  in(B)=U out(C) : C Vorgaenger von B */
  179.             if(g==fg) memcpy(g->rd_in,rd_parms,dsize);
  180.                 else  memset(g->rd_in,0,dsize);
  181.             lp=g->in;
  182.             while(lp){
  183.                 if(!lp->graph) ierror(0);
  184.                 if(lp->graph->branchout==g||!lp->graph->end||lp->graph->end->code!=BRA)
  185.                     bvunite(g->rd_in,lp->graph->rd_out,dsize);
  186.                 lp=lp->next;
  187.             }
  188.             /*  out(b)=gen(B) U (in(B)-kill(B)  */
  189.             memcpy(tmp,g->rd_in,dsize);
  190.             bvdiff(tmp,g->rd_kill,dsize);
  191.             bvunite(tmp,g->rd_gen,dsize);
  192.             if(!bvcmp(tmp,g->rd_out,dsize)){changed=1;memcpy(g->rd_out,tmp,dsize);}
  193.             g=g->normalout;
  194.         }
  195.     }while(changed);
  196.     if(DEBUG&1024) printf("\n");
  197.     free(tmp);
  198. }
  199. void calc(int c,int t,union atyps *q1,union atyps *q2,union atyps *z)
  200. /*  berechnet z:=q1 op q2; mit Konstanten                           */
  201. {
  202.     zpointer z1,z2;zdouble d1,d2;zlong l1,l2;zulong u1,u2;
  203.     eval_const(q1,t);
  204.     z1=vpointer;d1=vdouble;l1=vlong;u1=vulong;
  205.     if(q2){
  206.         eval_const(q2,t);
  207.         z2=vpointer;d2=vdouble;l2=vlong;u2=vulong;
  208.     }
  209.     if(c==ADD){ vdouble=zdadd(d1,d2);vlong=zladd(l1,l2);vulong=zuladd(u1,u2);}
  210.     if(c==SUB){ vdouble=zdsub(d1,d2);vlong=zlsub(l1,l2);vulong=zulsub(u1,u2);}
  211.     if(c==MULT){ vdouble=zdmult(d1,d2);vlong=zlmult(l1,l2);vulong=zulmult(u1,u2);}
  212.     if(c==DIV||c==MOD){
  213.         if(zdeq(d2)&&zleq(l2)&&zuleq(u2)){
  214.             error(84);
  215.             vlong=l2zl(0L);vulong=ul2zul(0L);vdouble=zl2zd(l1);
  216.         }else{
  217.             if(c==DIV){vdouble=zddiv(d1,d2);vlong=zldiv(l1,l2);vulong=zuldiv(u1,u2);}
  218.              else     {vlong=zlmod(l1,l2);vulong=zulmod(u1,u2);}
  219.         }
  220.     }
  221.     if(c==AND){ vlong=zland(l1,l2);vulong=zuland(u1,u2);}
  222.     if(c==OR){ vlong=zlor(l1,l2);vulong=zulor(u1,u2);}
  223.     if(c==XOR){ vlong=zlxor(l1,l2);vulong=zulxor(u1,u2);}
  224.     if(c==LSHIFT){ vlong=zllshift(l1,l2);vulong=zullshift(u1,u2);}
  225.     if(c==RSHIFT){ vlong=zlrshift(l1,l2);vulong=zulrshift(u1,u2);}
  226.     if(c==MINUS){ vdouble=zdneg(d1);vlong=zlneg(l1);vulong=zulneg(u1);}
  227.     if(c==KOMPLEMENT){ vlong=zlkompl(l1);vulong=zulkompl(u1);}
  228.  
  229.     vint=zl2zi(vlong);vshort=zl2zs(vlong);vchar=zl2zc(vlong);
  230.     vuint=zul2zui(vulong);vushort=zul2zus(vulong);vuchar=zul2zuc(vulong);
  231.     vfloat=zd2zf(vdouble);
  232.     insert_const2(z,t);
  233. }
  234.  
  235. int fold(struct IC *p)
  236. /*  wertet konstante ICs aus    */
  237. {
  238.     int c;
  239.     if(!p) ierror(0);
  240.     c=p->code;
  241.     if(c==ADDI2P||c==SUBIFP||c==SUBPFP||c==ASSIGN||c==PUSH||c==SETRETURN) return(0);
  242.     if(DEBUG&1024) {printf("folding IC:\n");pric2(stdout,p);}
  243.     if(c==TEST||c==COMPARE){
  244.         union atyps val;int cc; /*  condition codes */
  245.         struct IC *bp;
  246.         if(c==TEST){
  247.             eval_const(&p->q1.val,p->typf);
  248.             if(zleq(vlong)&&zuleq(vulong)&&zdeq(vdouble)&&zpeq(vpointer)) cc=0; else cc=1;
  249.         } else cc=compare_const(&p->q1.val,&p->q2.val,p->typf);
  250.         if(DEBUG&1024) printf("(cc=%d; comparison eliminated)\n",cc);
  251.         bp=p->next; remove_IC(p);
  252.         while(1){   /*  zugehoerigen Branch suchen  */
  253.             if(!bp||bp->code==LABEL||bp->code==BRA) ierror(0);
  254.             c=bp->code;
  255.             if(c>=BEQ&&c<=BGT) break;
  256.             bp=bp->next;
  257.         }
  258.         if((c==BEQ&&cc==0)||(c==BNE&&cc!=0)||(c==BLT&&cc<0)||(c==BGT&&cc>0)||(c==BLE&&cc<=0)||(c==BGE&&cc>=0)){
  259.             if(DEBUG&1024){ printf("changed following branch to BRA:\n");pric2(stdout,bp);}
  260.             bp->code=BRA;
  261.         }else{
  262.             if(DEBUG&1024){ printf("removed following branch:\n");pric2(stdout,bp);}
  263.             remove_IC(bp);
  264.         }
  265.         return(1);
  266.     }
  267.     if(c>=CONVCHAR&&c<=CONVULONG){
  268.         int t;
  269.         if(c==CONVCHAR) t=CHAR;
  270.         if(c==CONVUCHAR) t=UNSIGNED|CHAR;
  271.         if(c==CONVSHORT) t=SHORT;
  272.         if(c==CONVUSHORT) t=UNSIGNED|SHORT;
  273.         if(c==CONVINT) t=INT;
  274.         if(c==CONVUINT) t=UNSIGNED|INT;
  275.         if(c==CONVLONG) t=LONG;
  276.         if(c==CONVULONG) t=UNSIGNED|LONG;
  277.         if(c==CONVFLOAT) t=FLOAT;
  278.         if(c==CONVDOUBLE) t=DOUBLE;
  279.         if(c==CONVPOINTER) t=POINTER;
  280.         eval_const(&p->q1.val,t);
  281.         insert_const2(&p->q1.val,p->typf);
  282.     }else calc(c,p->typf,&p->q1.val,&p->q2.val,&p->q1.val);
  283.     p->q2.flags=0;
  284.     p->q2.reg=sizetab[p->typf&15];
  285.     p->code=ASSIGN;
  286.     if(DEBUG&1024){printf("becomes\n");pric2(stdout,p);}
  287.     return(1);
  288. }
  289. int propagate(struct obj *o,int replace)
  290. /*  versucht, Objekte durch Konstanten zu ersetzen und erkennt manche   */
  291. /*  nicht initialisierten Variablen; ist replace==0, wird nicht ersetzt */
  292. {
  293.     unsigned int i,valflag;union atyps val;
  294.     struct Var *copy,*v;struct IC *p;
  295. /*    if(DEBUG&1024){ printf("propagate():\n");scanf("%d",&i);}*/
  296.     if(!o||!o->v) ierror(0);
  297.     i=o->v->index;
  298.     if(o->flags&DREFOBJ) i+=vcount-rcount;
  299.     if(DEBUG&2048){
  300.         printf("propagate <%s>\n",o->v->identifier);
  301.         if(o->flags&DREFOBJ) printf("(DREFOBJ)");
  302.         printf("\nall reaching definitions:\n");print_rd(rd_defs);
  303.         printf("definitions of object:\n");print_rd(defs[i]);
  304.     }
  305.     memcpy(rd_tmp,rd_defs,dsize);
  306.     bvintersect(rd_tmp,defs[i],dsize);  /*  nur Def. von v betrachten   */
  307. /*    if(DEBUG&1024){printf("matching reaching definitions:\n");print_rd(rd_tmp);printf("found rds:\n");}
  308.     if(DEBUG&1024){printf("starting propagate-loop\n");scanf("%d",&i);}*/
  309.     valflag=0;copy=0;
  310.     for(i=1;i<=dcount;i++){
  311.         if(BTST(rd_tmp,i)){
  312.             p=dlist[i];
  313. /*            if(DEBUG&1024) pric2(stdout,p);*/
  314. /*            if(p->q2.reg!=size) {if(DEBUG&2048) printf("size wrong\n");return(0);}*/
  315.             if(compare_objs(o,&p->z,p->typf)) return(0);
  316.             if(p->code!=ASSIGN) return(0);  /*  damit kann ich nichts anfangen  */
  317.             if(!(p->q1.flags&(VAR|KONST))) ierror(0);
  318.             if(p->q1.flags&KONST){
  319.                 if(copy) return(0);     /*  Kopien+Konst gemischt   */
  320.                 if(valflag){
  321.                     /*  wenn mehr als eine Konstante, muessen alle gleich sein  */
  322.                     if(compare_const(&p->q1.val,&val,p->typf)) return(0);
  323.                 }else{
  324.                     valflag=1;val=p->q1.val;
  325.                 }
  326.             }else{
  327.                 if(valflag) return(0);  /*  Kopien+Konst gemischt   */
  328.                 if(copy){
  329.                     /*  alle Kopien muessen gleich sein */
  330.                     if(copy!=p->q1.v) return(0);
  331.                 }else{
  332.                     copy=p->q1.v;
  333.                 }
  334.             }
  335.         }
  336.     }
  337.     if(copy){
  338.     /*  fuer copy propagation muesste man hier noch mehr testen     */
  339.         return(0);
  340.         if(!replace) return(0);
  341.         if(DEBUG&1024){ printf("found possible copy <%s> for <%s>\n",copy->identifier,o->v->identifier);}
  342.         return(0);
  343.     }
  344.     /*  kann Konstante einsetzen    */
  345.     if(valflag){
  346.         if(!replace) return(0);
  347.         if(DEBUG&1024){ printf("can <%s> replace by constant\n",o->v->identifier);}
  348.         o->val=val;
  349. /*        o->flags&=~VAR;
  350.         o->flags|=KONST;*/
  351.         o->flags=KONST;
  352.         return(1);
  353.     }
  354.     /*  gar keine Definition gefunden   */
  355.     v=o->v;
  356.     if((v->vtyp->flags&15)>POINTER) return(0);  /*  bei structs keine Meldung   */
  357.     if(v->nesting==0||v->storage_class==STATIC||v->storage_class==EXTERN){
  358.     /*  wenn fuer eine statische Variable keine Def. existiert, gilt:   */
  359.     /*  v global und Fkt main(): initialisierung oder 0                 */
  360.     /*  v constant             :    "             "                     */
  361.     /*  v statisch und !(USEDASADR|USEDASDEST)                          */
  362.         if((v->vtyp->flags&15)>=POINTER) return(0); /* nur fuer arith.  */
  363.         if(replace&&(v->vtyp->flags&CONST)||(v->nesting>0&&!(v->flags&(USEDASADR|USEDASDEST)))/*||nocall*/){
  364.             if(v->clist){
  365.                 o->val=v->clist->val;
  366.             }else{
  367.                 if(!(v->flags&DEFINED)) return(0);
  368.                 if(0/*norek*/){
  369.                     val.vlong=l2zl(0L);eval_const(&val,LONG);
  370.                     insert_const2(&o->val,v->vtyp->flags);
  371.                 }else return(0);
  372.             }
  373.             o->flags&=~VAR;
  374.             o->flags|=KONST;
  375.             return(1);
  376.         }
  377.         return(0);
  378.     }
  379.     if((v->vtyp->flags&15)!=FUNKT&&!(v->flags&USEDBEFORE)){
  380.         error(171,v->identifier);v->flags|=USEDBEFORE;
  381.         if(!*v->identifier) {probj(stdout,o,0,1);prd(stdout,v->vtyp);printf("; offset=%d\n");}
  382.     }
  383.     return(0);
  384. }
  385. int constant_propagation(struct flowgraph *fg,int global)
  386. /*  sucht nach konstanten Ausdruecken und nicht definierten Variablen   */
  387. /*  wenn global!=0, dann werden reaching definitions benutzt und global */
  388. /*  optimiert, ansonsten nur innerhalb von basic blocks                 */
  389. {
  390.     struct IC *p;int changed=0,i;struct flowgraph *g;
  391.     if(DEBUG&1024){printf("trying constant propagation\n");}
  392.     rd_defs=mymalloc(dsize);
  393.     rd_tmp=mymalloc(dsize);
  394.     g=fg;
  395.     while(g){
  396.         if(global) memcpy(rd_defs,g->rd_in,dsize);
  397.             else   memset(rd_defs,~0,dsize);
  398.         p=g->start;
  399.         while(p){
  400. /*            if(DEBUG&1024){print_rd(rd_defs);pric2(stdout,p);}*/
  401.             if(p->code!=ADDRESS&&(p->typf&15)<=POINTER&&(p->code<LABEL||p->code>BRA)){
  402.                 int i;
  403.                 if((p->q1.flags&(VAR|VARADR))==VAR){
  404.                     i=p->q1.v->index;
  405.                     if(p->q1.flags&DREFOBJ) i+=vcount-rcount;
  406.                     if(!BTST(rd_defs,i+dcount+1))
  407.                         changed|=propagate(&p->q1,1);
  408.                 }
  409.                 if((p->q2.flags&(VAR|VARADR))==VAR){
  410.                     i=p->q2.v->index;
  411.                     if(p->q2.flags&DREFOBJ) i+=vcount-rcount;
  412.                     if(!BTST(rd_defs,i+dcount+1))
  413.                         changed|=propagate(&p->q2,1);
  414.                 }
  415.             }
  416.             /*  sollte eigentlich nichts bringen, ausser evtl. Meldung  */
  417.             /*  bei unitiialisierter Variablen                          */
  418.             if(((p->z.flags&(VAR|DREFOBJ))==(VAR|DREFOBJ))&&!BTST(rd_defs,p->z.v->index+dcount+vcount-rcount+1))
  419.                 changed|=propagate(&p->z,0);
  420.  
  421.             if((p->z.flags&(VAR|DREFOBJ))==VAR){
  422.                 if(p->z.v->nesting==0||(p->z.v->flags&USEDASADR))
  423.                     bvunite(rd_defs,rd_drefs,dsize);
  424.             }
  425.             if(p->code==CALL||(p->z.flags&DREFOBJ)){
  426.                 bvunite(rd_defs,rd_globals,dsize);
  427.                 bvunite(rd_defs,rd_address,dsize);
  428.                 if(p->code==CALL) bvunite(rd_defs,rd_statics,dsize);
  429.             }
  430.             if(p->defindex){
  431.                 unsigned int i=p->z.v->index;
  432.                 if(p->z.flags&DREFOBJ) i+=vcount-rcount;
  433.                 bvdiff(rd_defs,defs[i],dsize);
  434.                 BSET(rd_defs,p->defindex);
  435.                 if(i<rcount) bvunite(rd_defs,defs[i+vcount-rcount],dsize);
  436.             }
  437.             if(p==g->end) break;
  438.             p=p->next;
  439.         }
  440.         g=g->normalout;
  441.     }
  442.  
  443.     gchanged|=changed;
  444.     for(i=0;i<vcount;i++) free(defs[i]);
  445.     free(defs);
  446.     free(dlist);
  447.     free(rd_globals);
  448.     free(rd_statics);
  449.     free(rd_address);
  450.     free(rd_drefs);
  451.     free(rd_tmp);
  452.     free(rd_defs);
  453.     free(rd_parms);
  454.     return(changed);
  455. }
  456.  
  457.